#ifndef __PEER_CONNECTION_H
#define __PEER_CONNECTION_H
#include <rtc_base/rtc_certificate.h>
#include <rtc_base/third_party/sigslot/sigslot.h>
#include <system_wrappers/include/clock.h>
#include <api/media_types.h>

#include "base/event_loop.h"
#include "pc/session_description.h"
#include "ice/ice_credentials.h"
#include "pc/transport_controller.h"
#include "video/video_receive_stream.h"
#include "video/video_send_stream.h"
#include "audio/audio_receive_stream.h"
#include "audio/audio_send_stream.h"
#include <string>
#include <memory>
namespace xrtc
{
    struct RttTime
    {
        RttTime(int64_t time, int64_t rtt_ms) : time(time), rtt_ms(rtt_ms)
        {
        }
        int64_t time;
        int64_t rtt_ms;
    };

    struct RTCOfferAnswerOptions
    {
        bool send_audio = true;
        bool send_video = true;
        bool recv_audio = true;
        bool recv_video = true;
        bool use_rtp_mux = true; // 是否开启bind选项(通道复用)
        bool use_rtcp_mux = true;
        bool dtls_on = true;
    };

    class PeerConnection : public sigslot::has_slots<>, public RtpRtcpModuleObserver
    {
    public:
        enum class TransportMode
        {
            kTransparent,
            kLive
        };
        PeerConnection(EventLoop *el, PortAllocator *allocator);
        // ~PeerConnection();
        int Init(rtc::RTCCertificate *certificate);
        std::string CreateOffer(const RTCOfferAnswerOptions &options);
        int SetRemoteSdp(const std::string &sdp);
        void Destory();
        void SetSrInfo(webrtc::MediaType media_type, uint32_t rtp_timestamp, webrtc::NtpTime ntp);
        int SendPacket(webrtc::MediaType media_type, const webrtc::RtpPacketToSend &packet);
        SessionDescription *RemoteDesc() { return remote_desc_.get(); }
        SessionDescription *LocalDesc() { return local_desc_.get(); }
        void AddAudioSource(const std::vector<StreamParams> &source)
        {
            audio_source_ = source;
        }
        void AddVideoSource(const std::vector<StreamParams> &source)
        {
            video_source_ = source;
        }
        int SendRtp(const char *data, size_t len);
        int SendRtcp(const char *data, size_t len);
        void set_mode(const std::string &mode);
        void set_pli(bool is_pli) { is_pli_ = is_pli; }
        bool IsTransparent() const { return transport_mode_ == TransportMode::kTransparent; }
        bool IsLive() const { return transport_mode_ == TransportMode::kLive; }
        sigslot::signal2<PeerConnection *, PeerConnectionState> SignalConnectionState;

        // transport 模式
        sigslot::signal3<PeerConnection *, rtc::CopyOnWriteBuffer *, int64_t> SignalRtpPacketReceived;
        sigslot::signal3<PeerConnection *, rtc::CopyOnWriteBuffer *, int64_t> SignalRtcpPacketReceived;
        // live 模式
        sigslot::signal3<PeerConnection *, webrtc::MediaType, const webrtc::RtpPacketReceived &> SignalRtpPacket;
        sigslot::signal4<PeerConnection *, webrtc::MediaType, uint32_t, webrtc::NtpTime> SignalSrInfo;
        sigslot::signal3<PeerConnection *, webrtc::MediaType, const std::vector<uint16_t> &> SignalNackReceived;
        sigslot::signal2<PeerConnection *, RtpFrameObject *> SignalFrame;

    private:
        ~PeerConnection();
        void OnCandidateAllocateDone(TransportController *transport_controller,
                                     const std::string &transport_name, IceCandidateComponent component,
                                     const std::vector<Candidate> &candidates);
        void OnConnectionState(TransportController *, PeerConnectionState state);
        void OnRtcpPacketReceived(TransportController *, rtc::CopyOnWriteBuffer *packet, int64_t ts);
        void OnRtpPacketReceived(TransportController *, rtc::CopyOnWriteBuffer *packet, int64_t ts);
        void OnLocalRtcpPacket(webrtc::MediaType media_type, const uint8_t *data, size_t len) override;
        void OnFrame(std::unique_ptr<RtpFrameObject> frame) override;
        void OnRtpPacket(webrtc::MediaType media_type, const webrtc::RtpPacketReceived &packet) override;
        void OnSrInfo(webrtc::MediaType media_type, uint32_t rtp_timestamp, webrtc::NtpTime ntp) override;
        void OnNackReceived(webrtc::MediaType media_type, const std::vector<uint16_t> &nack_list) override;
        void OnRttUpdate(int64_t rtt_ms) override;

        webrtc::MediaType GetMediaType(uint32_t ssrc) const;
        void CreateVideoReceiveStream(VideoContentDescription *video_content);
        void CreateVideoSendStream(VideoContentDescription *video_content);
        void CreateAudioReceiveStream(AudioContentDescription *audio_content);
        void CreateAudioSendStream(AudioContentDescription *audio_content);

        friend void DestoryTimerCb(EventLoop *el, TimerWatcher *w, void *date);

    private:
        EventLoop *el_;
        webrtc::Clock *clock_;
        bool is_dtls_ = true;
        bool is_pli_ = false;
        TransportMode transport_mode_ = TransportMode::kLive;
        std::unique_ptr<SessionDescription> local_desc_;
        std::unique_ptr<SessionDescription> remote_desc_;

        rtc::RTCCertificate *certificate_ = nullptr;
        std::unique_ptr<TransportController> transport_controller_;
        TimerWatcher *destory_timer_ = nullptr;
        std::vector<StreamParams> audio_source_;
        std::vector<StreamParams> video_source_;
        uint32_t remote_audio_ssrc_ = 0;
        uint32_t remote_video_ssrc_ = 0;
        int audio_clockrate_ = 0;
        uint32_t remote_video_rtx_ssrc_ = 0;
        uint32_t local_audio_ssrc_ = 0;
        uint32_t local_video_ssrc_ = 0;
        uint32_t local_video_rtx_ssrc_ = 0;
        std::unique_ptr<VideoReceiveStream> video_receive_stream_;
        std::unique_ptr<AudioReceiveStream> audio_receive_stream_;
        std::unique_ptr<AudioSendStream> audio_send_stream_;
        std::unique_ptr<VideoSendStream> video_send_stream_;
        std::list<RttTime> rtt_reports_; // 缓存最近的rtt 的值
    };

} // namespace xrtc

#endif